package com.cash.loan.modular.user.controller;

import com.cash.loan.common.annotation.UserLogin;
import com.cash.loan.common.entity.UserInfo;
import com.cash.loan.common.exception.BizExceptionEnum;
import com.cash.loan.common.result.PageResult;
import com.cash.loan.common.result.ServerResponse;
import com.cash.loan.common.submessage.MessageService;
import com.cash.loan.common.upload.QiniuService;
import com.cash.loan.common.util.RedisUtil;
import com.cash.loan.config.properties.CacheTimeProperties;
import com.cash.loan.core.base.controller.BaseController;
import com.cash.loan.core.util.DateUtil;
import com.cash.loan.core.util.IpUtils;
import com.cash.loan.core.util.RandomUtil;
import com.cash.loan.core.util.TextValidator;
import com.cash.loan.modular.cash.service.ProductService;
import com.cash.loan.modular.cash.transfer.vo.ProductListVo;
import com.cash.loan.modular.user.dao.CashUserLoginMapper;
import com.cash.loan.modular.user.dao.CashUserMapper;
import com.cash.loan.modular.user.model.CashUserLogin;
import com.cash.loan.modular.user.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 用户管理controller
 * @author Administrator
 * @Date 2018-07-06 8:54
 */
@Api(description = "用户接口")
@RestController
@RequestMapping(value = "/user")
public class UserController extends BaseController{

    private static final Logger log = LoggerFactory.getLogger(UserController.class);

    /**
     * 校验码缓存
     */
    private static final String MESSAGE_CHECK_CODE = "message:code_";

    /**
     * 手机号发送间隔缓存
     */
    private static final String SHORT_MESSAGE_LIMIT = "message:send:limit_";

    /**
     * 短信平台选择缓存
     */
    private static final String MESSAGE_PLATFORM = "message:platform";

    /**
     * 登录注册时默认的用户密码
     */
    private static final String DEFAULT_PWD = "123456";

    /**
     * phone黑名单
     */
    private static final String PHONE_BLACK_LIST = "phone_black_list:";

    private static final String IP_BLACK_LIST = "ip_black_list:";

    /**
     * java的user agent
     */
    private static final String USER_AGENT = "Apache-HttpClient";

    private static final String USER_AGENT_JAVA = "Java";

    private static final String REAL_AGENT = "okhttp/3.4.1";

    /**
     * 手机号次数限制
     */
    private static final long PHONE_LIMIT_COUNT = 5L;

    /**
     * ip次数限制
     */
    private static final long IP_LIMIT_COUNT = 5L;

    /**
     * 短信发送服务
     */
    @Autowired
    private MessageService messageService;

    /**
     * 缓存时间
     */
    @Autowired
    private CacheTimeProperties cacheTimeProperties;

    /**
     * redis工具类
     */
    @Autowired
    private RedisUtil redisUtil;

    /**
     * 七牛云服务
     */
    @Autowired
    private QiniuService qiniuService;

    /**
     * 用户管理
     */
    @Autowired
    private UserService userService;

    /**
     * 用户账号dao
     */
    @Autowired
    private CashUserLoginMapper userLoginMapper;

    /**
     * 用户dao
     */
    @Autowired
    private CashUserMapper userMapper;

    /**
     * 产品service
     */
    @Autowired
    private ProductService productService;

    /**
     * 发送短息
     * @param phone
     * @param type 0表示注册短信发送，1表示登录时的短信发送，2表示找密码短信发送（1和2暂时反过来）
     * @return
     */
    @ApiOperation("发送短信")
    @PostMapping(value = "/sendMessage")
    public ServerResponse sendMessage(@RequestParam(value = "phone") String phone,
                                      @RequestParam(value = "type") Integer type) throws InterruptedException {
        if(!TextValidator.isMobileExact(phone)) {
            return ServerResponse.getErrorMessage("手机号无效");
        }

        //手机号短信发送情况判断，1不再做判断
        Boolean isRegisted = userService.isExistedUser(phone);
        if(type == 0) {
            if(isRegisted) {
                return ServerResponse.getErrorMessage("手机号已被注册");
            }
        } else if(type == 2) {
            log.info("login type");
        } else if (type == 1) {
            if(!isRegisted) {
                return ServerResponse.getErrorMessage("手机号未注册");
            }
        }else if(type == 100){
            
        } else {
            return ServerResponse.getErrorMessage("参数错误，请重试");
        }

        log.info("time: {}, ip: {}, phone: {}, user-agent: {}", DateUtil.getTime(new Date()),
                IpUtils.getIpAddr(getHttpServletRequest()),phone,getHttpServletRequest().getHeader("User-Agent"));

        String userAgent = getHttpServletRequest().getHeader("User-Agent");
        if(!userAgent.contains(REAL_AGENT)) {
            log.info("来自:"+userAgent+"的请求被禁用, Real-Ip: {}",getHttpServletRequest().getHeader("X-Forwarded-For"));
            return ServerResponse.getSuccess("发送成功");
        }

        //通过ip限制短信发送
        String ip = IpUtils.getIpAddr(getHttpServletRequest());
        if(redisUtil.existKey(IP_BLACK_LIST + ip)) {
            String countStr = (String) redisUtil.get(IP_BLACK_LIST + ip);
            long count = Long.valueOf(countStr);
            if(count > IP_LIMIT_COUNT) {
                log.info("{} : ip被禁用",ip);
                return ServerResponse.getSuccess("短信发送过于频繁,请稍后重试");
            } else {
                redisUtil.incr(IP_BLACK_LIST + ip,1L);
            }
        } else {
            redisUtil.incr(IP_BLACK_LIST + ip,1L);
        }

        // 通过手机号黑名单限制短信发送
        if(redisUtil.existKey(PHONE_BLACK_LIST +phone)) {
            String countStr = (String) redisUtil.get(PHONE_BLACK_LIST + phone);
            long count = Long.parseLong(countStr);
            if(count > PHONE_LIMIT_COUNT) {
                log.info("{} : phone被禁用",phone);
                return ServerResponse.getErrorMessage("短信发送过于频繁,请稍后重试");
            } else {
                redisUtil.incr(PHONE_BLACK_LIST +phone,1L);
            }
        } else {
            redisUtil.incr(PHONE_BLACK_LIST +phone,1L);
        }

        //生成验证码并发送
        Random random = new Random();
        int intCode = RandomUtil.nextInt(random,100000,999999);
        String code = String.valueOf(intCode);

        Boolean isSendTime = redisUtil.existKey(SHORT_MESSAGE_LIMIT + phone);
        if(isSendTime) {
            return ServerResponse.getErrorMessage("短信发送过于频繁,请稍后重试");
        }
        Boolean sendResult;
        if(checkMessagePaltfrom() == 0) {
            sendResult = messageService.sendMessage(phone,code);
        } else {
            sendResult = messageService.sendNewMessage(phone,code);
        }
        if(sendResult) {
            //缓存code
            redisUtil.set(MESSAGE_CHECK_CODE + phone,code,cacheTimeProperties.getMessage());
            //缓存发送间隔
            redisUtil.set(SHORT_MESSAGE_LIMIT + phone,String.valueOf(1),cacheTimeProperties.getInterval());
            return ServerResponse.getSuccess("发送成功");
        } else {
            return ServerResponse.getErrorMessage("短信发送失败");
        }
    }

    /**
     * 用户注册
     * @param phone
     * @param code
     * @return
     */
    @ApiOperation("用户注册")
    @PostMapping(value = "/register")
    public ServerResponse register(@RequestParam(value = "phone") String phone,
                                   @RequestParam(value = "code") String code,
                                   @RequestParam(value = "password" ) String password,
                                   @RequestParam(value = "regFrom",required = false) String regFrom) {
        HttpServletRequest request = getHttpServletRequest();
        if(StringUtils.isBlank(phone)) {
            return ServerResponse.getErrorMessage("手机号不能为空");
        }
        if(!TextValidator.isMobileExact(phone)) {
            return ServerResponse.getErrorMessage("手机号无效");
        }
        if(StringUtils.isBlank(password)) {
            return ServerResponse.getErrorMessage("密码不能为空");
        }
        if(password.length() < 6 || password.length() > 20) {
            return ServerResponse.getErrorMessage("密码不符合要求");
        }
        if(StringUtils.isBlank(code)) {
            return ServerResponse.getErrorMessage("验证码不能为空");
        }
        String cacheCode = (String) redisUtil.get(MESSAGE_CHECK_CODE +phone);
        if(StringUtils.isBlank(cacheCode)) {
            return ServerResponse.getErrorMessage("验证码已失效");
        }
        if(!code.equals(cacheCode)) {
            return ServerResponse.getErrorMessage("验证码错误");
        }

        //判断手机号是否已经被注册
        Boolean isRegisted = userService.isExistedUser(phone);
        if(isRegisted) {
            return ServerResponse.getErrorMessage("手机号已被注册");
        }

        String ip = IpUtils.getIpAddr(request);
        Map<String,String> result = userService.register(phone,password,ip,regFrom);
        return ServerResponse.getSuccess("success",result);
    }

    /**
     * 密码登录
     * @param phone
     * @param password
     * @return
     */
    @ApiOperation("用户密码登录")
    @PostMapping(value = "/login")
    public ServerResponse passwordLogin(@RequestParam(value = "phone") String phone,
                                        @RequestParam(value = "password") String password) {
        HttpServletRequest request = getHttpServletRequest();
        String ip = IpUtils.getIpAddr(request);
        if(StringUtils.isBlank(phone)) {
            return ServerResponse.getErrorMessage("手机号不能为空");
        }
        if(StringUtils.isBlank(password)) {
            return ServerResponse.getErrorMessage("手机号不能为空");
        }
        Boolean isExist = userService.isExistedUser(phone);
        if(!isExist) {
            return ServerResponse.getErrorMessage("用户不存在");
        }
        UserInfo userInfo = userService.checkPhoneAndPwd(phone,password,ip);
        if(userInfo == null) {
            return ServerResponse.getErrorMessage("密码错误");
        }
        Map<String,String> result = userService.productToken(userInfo);
        return ServerResponse.getSuccess("success",result);
    }

    /**
     * 短信登录
     * @param phone
     * @param code
     * @return
     */
    @ApiOperation("短信登录")
    @PostMapping(value = "/smsLogin")
    public ServerResponse smsLogin(@RequestParam(value = "phone") String phone,
                                   @RequestParam(value = "code") String code,
                                   @RequestParam(value = "regFrom",required = false) String regFrom) {
        HttpServletRequest request = getHttpServletRequest();
        String ip = IpUtils.getIpAddr(request);
        if(StringUtils.isBlank(phone)) {
            return ServerResponse.getErrorMessage("手机号不能为空");
        }
        if(!TextValidator.isMobileExact(phone)) {
            return ServerResponse.getErrorMessage("手机号无效");
        }
        if(StringUtils.isBlank(code)) {
            return ServerResponse.getErrorMessage("验证码不能为空");
        }
        String cacheCode = (String) redisUtil.get(MESSAGE_CHECK_CODE + phone);
        if(StringUtils.isBlank(cacheCode)) {
            return ServerResponse.getErrorMessage("验证码已失效");
        }
        if(!code.equals(cacheCode)) {
            return ServerResponse.getErrorMessage("验证码错误");
        }

        //如果用户未注册，可直接完成注册
        Boolean isExist = userService.isExistedUser(phone);
        if(!isExist) {
            Map<String,String> result = userService.register(phone,DEFAULT_PWD,ip,regFrom);
            return ServerResponse.getSuccess("success",result);
        }

        UserInfo userInfo = userLoginMapper.getUserInfo(phone);
        CashUserLogin userLogin = new CashUserLogin();
        userLogin.setId(userInfo.getUserId());
        userLogin.setIp(ip);
        userLoginMapper.updateById(userLogin);
        userInfo.setPhone(phone);
        Map<String,String> result = userService.productToken(userInfo);
        return ServerResponse.getSuccess("success",result);
    }

    /**
     * 获取用户信息
     * @param userInfo
     * @return
     */
    @ApiOperation("获取用户信息")
    @PostMapping(value = "/userInfo")
    public ServerResponse userInfo(@UserLogin UserInfo userInfo,
                                   @RequestHeader(value = "Access-Token") String token) {
        if(userInfo == null) {
            return ServerResponse.getErrorCodeMessage(BizExceptionEnum.TOKEN_ERROR.getCode(),"用户未登录");
        }
        Map<String,Object> userDetailInfo = userService.getUserInfo(userInfo.getId());
        return ServerResponse.getSuccess("success",userDetailInfo);
    }

    /**
     * 更新用户资料
     * @param token
     * @param userInfo
     * @param type
     * @param content
     * @return
     */
    @ApiOperation("用户更新")
    @PostMapping(value = "/update")
    public ServerResponse updateUserInfo(@RequestHeader(value = "Access-Token") String token,
                                         @UserLogin UserInfo userInfo,
                                         @RequestParam(value = "type") String type,
                                         @RequestParam(value = "content") String content) {
        if(userInfo == null) {
            return ServerResponse.getErrorCodeMessage(BizExceptionEnum.TOKEN_ERROR.getCode(),"用户未登录");
        }
        if("nickName".equals(type)) {
            if(StringUtils.isBlank(content)) {
                return ServerResponse.getErrorMessage("昵称不能为空");
            }
        }
        if("idCard".equals(type)) {
            if(StringUtils.isNoneBlank(content)) {
                if(!TextValidator.isIdCard(content)) {
                    return ServerResponse.getErrorMessage("身份证号不符合要求");
                }
            }
        }
        if("age".equals(type)) {
            if(!TextValidator.isNum(content)) {
                return ServerResponse.getErrorMessage("输入不符合年龄要求");
            }
        }
        Boolean result = userService.updateUser(type,content,userInfo.getId());
        if(!result) {
            return ServerResponse.getErrorMessage("用户更新失败");
        }
        return ServerResponse.getSuccess("更新成功");
    }

    /**
     * 更新用户头像
     * @param avatar
     * @return
     * @throws IOException
     * @throws
     */
    @ApiOperation("用户头像上传")
    @PostMapping(value = "/updateAvatar")
    public ServerResponse updateAvatar(@RequestHeader(value = "Access-Token") String token,
                                       @UserLogin UserInfo userInfo,
                                       @RequestPart("avatar") MultipartFile avatar) throws IOException {
        if(userInfo == null) {
            return ServerResponse.getErrorCodeMessage(BizExceptionEnum.TOKEN_ERROR.getCode(),"用户未登录");
        }
        if(avatar.getSize() > 10 * 1024 * 1024) {
            return ServerResponse.getErrorMessage("头像大小不能超过10M");
        }
        String filenameExtension = avatar.getOriginalFilename().substring(avatar.getOriginalFilename().lastIndexOf("."), avatar.getOriginalFilename().length());
        InputStream content = avatar.getInputStream();
        String pictureAddr = qiniuService.upload(filenameExtension,content);
        userMapper.updateAvatar("/"+pictureAddr,userInfo.getId());
        Map<String,String> result = new HashMap<String,String>();
        result.put("avatarUrl",qiniuService.getUrl("/"+pictureAddr));
        return ServerResponse.getSuccess("update success",result);
    }

    /**
     * 设置密码
     * @param token
     * @param userInfo
     * @param password
     * @return
     */
    @ApiOperation("修改密码/设置密码")
    @PostMapping(value = "/updatePwd")
    public ServerResponse updatePassword(@RequestHeader(value = "Access-Token") String token,
                                         @UserLogin UserInfo userInfo,
                                         @RequestParam(value = "password") String password) {
        if(userInfo == null) {
            return ServerResponse.getErrorCodeMessage(BizExceptionEnum.TOKEN_ERROR.getCode(),"用户未登录");
        }
        Boolean isSuccess = userService.updatePassword(userInfo.getUserId(),password);
        if(!isSuccess) {
            return ServerResponse.getErrorMessage("更新失败");
        }
        return ServerResponse.getSuccess("更新成功");
    }

    /**
     * 用户退出
     * @param token
     * @param userInfo
     * @return
     */
    @ApiOperation("用户注销")
    @PostMapping(value = "/logout")
    public ServerResponse logout(@RequestHeader(value = "Access-Token") String token,
                                 @UserLogin UserInfo userInfo) {
        if(userInfo == null) {
            return ServerResponse.getErrorCodeMessage(BizExceptionEnum.TOKEN_ERROR.getCode(),"用户未登录");
        }
        redisUtil.delete(token);
        return ServerResponse.getSuccess("退出成功");
    }

    @ApiOperation("找回密码")
    @PostMapping(value = "/findPassword")
    public ServerResponse findPassword(@RequestParam(value = "phone") String phone,
                                       @RequestParam(value = "code") String code,
                                       @RequestParam(value = "password" ) String password) {
        if(StringUtils.isBlank(phone)) {
            return ServerResponse.getErrorMessage("手机号不能为空");
        }
        if(!TextValidator.isMobileExact(phone)) {
            return ServerResponse.getErrorMessage("手机号无效");
        }
        String cacheCode = (String) redisUtil.get(MESSAGE_CHECK_CODE + phone);
        if(StringUtils.isBlank(cacheCode)) {
            return ServerResponse.getErrorMessage("验证码已失效");
        }
        if(!code.equals(cacheCode)) {
            return ServerResponse.getErrorMessage("验证码错误");
        }
        if(StringUtils.isBlank(password)) {
            return ServerResponse.getErrorMessage("密码不能为空");
        }
        if(password.length() < 6 || password.length() > 20) {
            return ServerResponse.getErrorMessage("密码不符合要求");
        }
        if(StringUtils.isBlank(code)) {
            return ServerResponse.getErrorMessage("验证码不能为空");
        }

        //判断手机号是否已经被注册
        Boolean isRegisted = userService.isExistedUser(phone);
        if(!isRegisted) {
            return ServerResponse.getErrorMessage("手机号未注册");
        }

        Boolean result = userService.updatePasswordByPhone(phone,password);

        if(!result) {
            return ServerResponse.getErrorMessage("更新密码失败");
        }
        return ServerResponse.getSuccess("更新密码成功");
    }

    @ApiOperation("用户产品申请列表")
    @GetMapping(value = "/applyList")
    public ServerResponse userApplyList(@RequestParam(value = "currentPage",required = false,defaultValue = "1") Integer currentPage,
                                        @RequestParam(value = "pageSize",required = false,defaultValue = "20") Integer pageSize,
                                        @RequestHeader(value = "Access-Token") String token,
                                        @UserLogin UserInfo userInfo) {
        if(userInfo == null) {
            return ServerResponse.getErrorCodeMessage(BizExceptionEnum.TOKEN_ERROR.getCode(),"用户未登录");
        }

        Long visitId = userInfo.getUserId();

        PageResult<ProductListVo> pageResult = userService.getUserApplyList(currentPage,pageSize,visitId);

        return ServerResponse.getSuccess("success",pageResult);
    }

    @ApiOperation("个人中心的推荐产品5条,降序")
    @GetMapping(value = "/recommend")
    public ServerResponse myRecommendProduct() {
        List<Map<String,Object>> productList = productService.getRecommendProduct();
        return ServerResponse.getSuccess("success",productList);
    }

    /**
     * 判断使用哪个短信平台（0:submail;1:企信通）
     * @return
     */
    private Integer checkMessagePaltfrom() {
        if(!redisUtil.existKey(MESSAGE_PLATFORM)) {
            redisUtil.set(MESSAGE_PLATFORM,String.valueOf(0));
            return 0;
        }
        String result = (String) redisUtil.get(MESSAGE_PLATFORM);
        return Integer.valueOf(result);
    }
}
